package com.zycfc.zsf.boot.web.filter;

import org.springframework.web.filter.*;
import com.zycfc.zsf.boot.redis.*;
import com.zycfc.zsf.boot.util.text.*;
import com.zycfc.zsf.boot.common.context.*;
import com.zycfc.zsf.boot.util.json.*;
import javax.servlet.http.*;
import com.zycfc.zsf.boot.web.wrapper.*;
import java.nio.charset.*;
import com.zycfc.zsf.boot.logback.core.*;
import com.zycfc.zsf.boot.redis.enums.*;
import com.zycfc.zsf.boot.web.util.*;
import java.net.*;
import com.zycfc.zsf.boot.logback.util.*;
import java.util.*;
import javax.servlet.*;
import java.io.*;
import org.slf4j.*;

public class HttpResponseInjectingTraceFilter extends GenericFilterBean
{
    private static final Logger log;
    private static final String REAL_REQ_IP_KEY = "Real-Req-IP";
    private static final String REAL_REQUEST_IP_KEY = "realRequestIp";
    private static final String OPEN_SCENE_KEY = "openScene";
    private static final String OPEN_BAFFLE_KEY = "openBaffle";
    private static final String CODE_CHECK_SWITCH_KEY = "zsf:codeCheckSwitch";
    private static final String CODE_CHECK_SWITCH_ON = "on";
    private boolean notProdEnv;
    private IRedisOperater redisOperater;
    
    public HttpResponseInjectingTraceFilter() {
    }
    
    public HttpResponseInjectingTraceFilter(final boolean notProdEnv, final IRedisOperater redisOperater) {
        this.notProdEnv = notProdEnv;
        this.redisOperater = redisOperater;
    }
    
    private boolean isFilter(final String requestPath) {
        return requestPath.contains("/api/") || requestPath.contains("/fpi/");
    }
    
    private boolean isActuator(final String requestPath) {
        return requestPath.contains("/actuator");
    }
    
    public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain filterChain) throws IOException, ServletException {
        final HttpServletRequest httpRequest = (HttpServletRequest)request;
        String zycfcTraceId = httpRequest.getHeader("ZYCFC-TRACE-ID");
        final String traceLevel = httpRequest.getHeader("traceLevel");
        final String localSpanParentId = httpRequest.getHeader("LOCAL-SPAN-PARENT-ID");
        final String realReqIp = httpRequest.getHeader("Real-Req-IP");
        String grayscaleFlag = httpRequest.getHeader("grayscaleFlag");
        if (StringUtils.isEmpty(grayscaleFlag)) {
            final Object obj = httpRequest.getAttribute("grayscaleFlag");
            grayscaleFlag = ((obj != null) ? ((String)obj) : null);
        }
        TraceUtil.begin("LOCAL-SPAN-PARENT-ID", localSpanParentId);
        TraceUtil.begin("LOCAL-SPAN-ID", UuidUtils.getUuid());
        if (!StringUtils.isEmpty(zycfcTraceId)) {
            TraceUtil.beginZycfcTrace(zycfcTraceId);
            ZsfRootContext.put("ZYCFC-TRACE-ID", zycfcTraceId);
            ZsfRootContext.put("traceLevel", TraceUtil.beginTraceLevelAddOne(traceLevel));
        }
        if (StringUtils.isNotEmpty(realReqIp)) {
            HttpResponseInjectingTraceFilter.log.debug("Real-Req-IP:{}", (Object)realReqIp);
            ZsfRootContext.put("realRequestIp", realReqIp);
        }
        final String openScene = httpRequest.getHeader("openScene");
        if (StringUtils.isNotEmpty(openScene)) {
            HttpResponseInjectingTraceFilter.log.debug("openScene:{}", (Object)openScene);
            ZsfRootContext.put("openScene", openScene);
        }
        final String openBaffleStr = httpRequest.getHeader("openBaffle");
        if (StringUtils.isNotEmpty(openBaffleStr)) {
            HttpResponseInjectingTraceFilter.log.debug("openBaffleStr:{}", (Object)openBaffleStr);
            ZsfRootContext.put("openBaffle", openBaffleStr);
        }
        final RequestWrapper wrapperRequest = new RequestWrapper(httpRequest);
        final String requestJson = this.getRequestParameter(wrapperRequest);
        if (JsonUtils.validate(requestJson)) {
            final Map<String, Object> tmpMap = (Map<String, Object>)JsonUtils.jsonToMap(requestJson);
            final String localTraceIdContext = String.valueOf(tmpMap.get("flowId"));
            TraceUtil.beginLocalTrace(localTraceIdContext);
            ZsfRootContext.put("LOCAL-TRACE-ID", localTraceIdContext);
            if (StringUtils.isEmpty(zycfcTraceId)) {
                zycfcTraceId = localTraceIdContext;
                TraceUtil.beginZycfcTrace(zycfcTraceId);
                ZsfRootContext.put("ZYCFC-TRACE-ID", zycfcTraceId);
                ZsfRootContext.put("traceLevel", TraceUtil.beginTraceLevelAddOne("0"));
            }
        }
        final String reqIp = httpRequest.getRemoteAddr();
        final int reqPort = httpRequest.getRemotePort();
        final String remoteServer = reqIp + ":" + reqPort;
        final String requestPath = httpRequest.getServletPath();
        final boolean isActuator = this.isActuator(requestPath);
        if (!isActuator) {
            HttpResponseInjectingTraceFilter.log.debug("Trace-header-ZYCFC-TRACE-ID: {}, LOCAL-SPAN-ID:{}, LOCAL-SPAN-PARENT-ID: {}", new Object[] { zycfcTraceId, TraceUtil.get("LOCAL-SPAN-ID"), localSpanParentId });
            HttpResponseInjectingTraceFilter.log.debug("forward-ip-view-xRealIp: {}, xForwardedFor: {}, xForwardedProto: {}", new Object[] { httpRequest.getHeader("X-Real-IP"), httpRequest.getHeader("X-Forwarded-For"), httpRequest.getHeader("X-Forwarded-Proto") });
        }
        final String requestMsg = (requestJson != null && requestJson.length() > 10240) ? requestJson.substring(0, 10240) : requestJson;
        if (!isActuator) {
            HttpResponseInjectingTraceFilter.log.info("\u8bf7\u6c42\u8def\u5f84:{}-\u62a5\u6587\u4f53\u957f\u5ea6:{}-\u62a5\u6587:{}", new Object[] { requestPath, (requestJson != null) ? requestJson.length() : 0, requestMsg });
        }
        final long beginTm = System.currentTimeMillis();
        final ResponseWrapper wrapperResponse = new ResponseWrapper((HttpServletResponse)response);
        filterChain.doFilter((ServletRequest)wrapperRequest, (ServletResponse)wrapperResponse);
        byte[] content = wrapperResponse.getContent();
        String responseMsg = "";
        final boolean isFlitler = this.isFilter(requestPath);
        String responseJson;
        if (content.length > 0) {
            try {
                final String result = new String(content, StandardCharsets.UTF_8);
                if (isFlitler) {
                    if (result.length() > 10240) {
                        HttpResponseInjectingTraceFilter.log.warn("reponse-size-toolong:{}", (Object)result.length());
                        responseMsg = result.substring(0, 10240);
                    }
                    else {
                        responseMsg = result;
                    }
                    responseJson = result;
                    if (!isActuator) {
                        HttpResponseInjectingTraceFilter.log.debug("\u54cd\u5e94\u62a5\u6587: " + responseMsg);
                    }
                }
                else {
                    responseJson = "\u54cd\u5e94\u62a5\u6587: \u4e0d\u6253\u5370";
                    if (!isActuator) {
                        HttpResponseInjectingTraceFilter.log.info("\u54cd\u5e94\u62a5\u6587: \u4e0d\u6253\u5370");
                    }
                }
            }
            catch (Exception e) {
                responseJson = "\u54cd\u5e94\u62a5\u6587: error";
                HttpResponseInjectingTraceFilter.log.error("\u6dfb\u52a0\u8fd4\u56de\u503c\u4fe1\u606f\u5f02\u5e38", (Throwable)e);
            }
        }
        else {
            responseJson = "\u54cd\u5e94\u62a5\u6587: 0byte";
            if (!isActuator) {
                HttpResponseInjectingTraceFilter.log.info("content.length <= 0");
            }
        }
        if (isFlitler) {
            final ApiTranInf apiTranInf = new ApiTranInf(reqIp, reqPort, requestPath, httpRequest.getMethod(), requestMsg, responseMsg, System.currentTimeMillis() - beginTm, "S");
            if (!StringUtils.isEmptyAll(responseJson) && JsonUtils.validate(responseJson)) {
                final Map<String, Object> responseMap = (Map<String, Object>)JsonUtils.jsonToMap(responseJson);
                String code = "0000000";
                String respMsg = "";
                if (responseMap != null) {
                    code = String.valueOf(responseMap.get("code"));
                    respMsg = String.valueOf(responseMap.get("message"));
                }
                apiTranInf.setRespCode(code);
                apiTranInf.setRespMsg(respMsg);
                if (!"0000000".equals(code)) {
                    apiTranInf.setExeSts("F");
                }
                if (this.notProdEnv && "on".equals(this.redisOperater.get("zsf:codeCheckSwitch", CacheTypeEnum.LOCAL))) {
                    final byte[] newContent = CheckRespCodeUtil.checkRespCode(responseMap, apiTranInf, this.redisOperater);
                    if (newContent != null && newContent.length > 0) {
                        content = newContent;
                    }
                }
            }
            if (requestPath.startsWith("lb:/fpi") || requestPath.startsWith("/fpi")) {
                final String emplyNo = httpRequest.getHeader("userEmplyNo");
                final String emplyName = httpRequest.getHeader("userName");
                if (StringUtils.isNotBlank((CharSequence)emplyNo)) {
                    apiTranInf.setEmplyNo(URLDecoder.decode(emplyNo, "utf-8"));
                }
                if (StringUtils.isNotBlank((CharSequence)emplyName)) {
                    apiTranInf.setEmplyName(URLDecoder.decode(emplyName, "utf-8"));
                }
            }
            HttpResponseInjectingTraceFilter.log.debug("grayscaleFlag: {}", (Object)grayscaleFlag);
            final boolean isGrayscale = "true".equals(grayscaleFlag);
            apiTranInf.setGrayscaleFlag(isGrayscale ? "1" : "0");
            LogUtil.printApiTran(apiTranInf);
        }
        try (final ServletOutputStream out = response.getOutputStream()) {
            out.write(content);
            out.flush();
        }
        catch (Exception e) {
            if (e instanceof IllegalStateException) {
                if (isFlitler) {
                    HttpResponseInjectingTraceFilter.log.warn(e.getMessage(), (Throwable)e);
                }
                else {
                    HttpResponseInjectingTraceFilter.log.warn(e.getMessage());
                }
            }
            else {
                HttpResponseInjectingTraceFilter.log.error(e.getMessage(), (Throwable)e);
            }
        }
        ZsfRootContext.remove("traceLevel");
        ZsfRootContext.remove("LOCAL-TRACE-ID");
        ZsfRootContext.remove("ZYCFC-TRACE-ID");
        if (ZsfRootContext.get("openScene") != null) {
            ZsfRootContext.remove("openScene");
        }
        if (ZsfRootContext.get("openBaffle") != null) {
            ZsfRootContext.remove("openBaffle");
        }
        TraceUtil.endTrace();
    }
    
    public String getRequestParameter(final RequestWrapper wrapperRequest) {
        if (null == wrapperRequest) {
            return null;
        }
        final String method = wrapperRequest.getMethod();
        if (StringUtils.isNotBlank((CharSequence)method) && "GET".equalsIgnoreCase(method)) {
            String params = wrapperRequest.getQueryString();
            try {
                if (StringUtils.isNotBlank((CharSequence)params)) {
                    params = URLDecoder.decode(params, "UTF-8");
                }
            }
            catch (UnsupportedEncodingException e) {
                HttpResponseInjectingTraceFilter.log.error(e.getMessage(), (Throwable)e);
            }
            return params;
        }
        return wrapperRequest.getBodyString((ServletRequest)wrapperRequest);
    }
    
    static {
        log = LoggerFactory.getLogger((Class)HttpResponseInjectingTraceFilter.class);
    }
}
